package org.suyafei.component;

import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.suyafei.config.WeChatPayApi;
import org.suyafei.config.WeChatPayConfig;
import org.suyafei.utils.CommonUtil;
import org.suyafei.vo.PayInfoVO;

import java.io.IOException;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Optional;

/**
 * @author 宿某人
 * @Date: 2022/03/03/16:49
 * @Description:
 */
@Component
@Slf4j
public class WeChatPayStrategy implements PayStrategy{

    @Autowired
    WeChatPayConfig payConfig;
    @Autowired
    private CloseableHttpClient wechatPayClient;

    @Override
    public String unifiedOrder(PayInfoVO payInfoVO) {
        //过期时间  RFC 3339格式
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX");
        //支付订单过期时间
        String timeExpire = sdf.format(new Date(System.currentTimeMillis() +payInfoVO.getOrderPayTimeoutMills()));

        JSONObject payObj = new JSONObject();
        payObj.put("mchid", payConfig.getMchId());
        payObj.put("out_trade_no", payInfoVO.getOutTradeNo());
        payObj.put("appid", payConfig.getWxPayAppid());
        payObj.put("description", "小滴课堂海量数据项目大课");
        payObj.put("notify_url", payConfig.getCallbackUrl());
        payObj.put("time_expire", timeExpire);


        int amount = payInfoVO.getPayFee().multiply(BigDecimal.valueOf(1)).intValue();

        JSONObject amountObj = new JSONObject();
        amountObj.put("total", amount);
        amountObj.put("currency", "CNY");
        payObj.put("amount", amountObj);


        //附属参数，可以用在回调携带
        payObj.put("attach", "{\"account_no\":" + payInfoVO.getAccountNo() + "}");

        String body = payObj.toJSONString();

        log.debug("请求参数{}",body);

        StringEntity entity = new StringEntity(body, "utf-8");
        entity.setContentType("application/json");

        HttpPost httpPost = new HttpPost(WeChatPayApi.NATIVE_ORDER);
        httpPost.setHeader("Accept", "application/json");
        httpPost.setEntity(entity);
        String result = "";
        try (CloseableHttpResponse response = wechatPayClient.execute(httpPost)){
             int statusCode = response.getStatusLine().getStatusCode();
             String responseStr = EntityUtils.toString(response.getEntity());
            log.debug("下单响应码{},响应体{}", statusCode, responseStr);

            if (statusCode == HttpStatus.OK.value()) {
                JSONObject jsonObject = JSONObject.parseObject(responseStr);
                result = Optional.ofNullable(jsonObject.getString("code_url")).orElse("");

            }else {
                log.error("下单失败响应码{},响应体{}", statusCode, responseStr);
            }
        } catch (IOException e) {
            log.error("微信支付响应异常:{}",e);
        }
        return result;
    }
    @Override
    public String refund(PayInfoVO payInfoVO) {
        return PayStrategy.super.refund(payInfoVO);
    }

    @Override
    public String queryPayStatus(PayInfoVO payInfoVO) {
        String outTradeNo = payInfoVO.getOutTradeNo();
        String url = String.format(WeChatPayApi.NATIVE_QUERY, outTradeNo, payConfig.getMchId());

        HttpGet httpGet = new HttpGet(url);
        httpGet.setHeader("Accept", "application/json");

        String result = "";
        //httpClient自动进行参数签名
        try (CloseableHttpResponse response = wechatPayClient.execute(httpGet)) {
            String responseStr = EntityUtils.toString(response.getEntity());
            int statusCode = response.getStatusLine().getStatusCode();
            log.debug("查询订单响应码={}，响应体={}", statusCode, responseStr);

            if (statusCode == HttpStatus.OK.value()) {
                JSONObject jsonObject = JSONObject.parseObject(responseStr);
                result = Optional.ofNullable(jsonObject.getString("trade_state")).orElse("");
            }else {
                log.error("查询失败响应码{},响应体{}", statusCode, responseStr);
            }
        } catch (Exception e) {
            log.error("微信查询响应异常{}",e);

        }
        return result;
    }

    @Override
    public String closeOrder(PayInfoVO payInfoVO) {
        String outTradeNo = payInfoVO.getOutTradeNo();
        JSONObject payObj = new JSONObject();
        payObj.put("mchid", payConfig.getMchId());

        final String body = payObj.toJSONString();
        StringEntity entity = new StringEntity(body, "utf-8");
        entity.setContentType("application/json");
        final String url = String.format(WeChatPayApi.NATIVE_CLOSE_ORDER, outTradeNo);
        HttpPost httpPost = new HttpPost(url);
        httpPost.setHeader("Accept", "application/json");
        httpPost.setEntity(entity);

        String result = "";
        try (CloseableHttpResponse response = wechatPayClient.execute(httpPost)){
             int statusCode = response.getStatusLine().getStatusCode();
            log.debug("关闭响应码{}", statusCode);
            if (statusCode == HttpStatus.NO_CONTENT.value()) {
                result = "CLOSE_SUCCESS";
            }
        } catch (IOException e) {
           log.error("关单响应异常{}",e);
        }
        return result;
    }
}
